module hashing

    use random_module, only: randu
    implicit none

contains

    !> get indexes
    function get_indexes(n)
        integer, intent(in) :: n
        integer :: get_indexes(3)
        real :: x

        associate (n3 => int(n**0.333))
            call randu(x, 0.666*n3, 1.333*n3)
            get_indexes(1) = x
            call randu(x, 0.666*n3, 1.333*n3)
            get_indexes(2) = x
            call randu(x, 0.1*n3, 1.0*n/(get_indexes(1)*get_indexes(2)))
            get_indexes(3) = x
        end associate

    end function get_indexes

    !> get hash
    function hash(i, j, k, n)
        integer, intent(in) :: i, j, k, n
        integer :: hash

        hash = modulo(ieor(ieor(73856093*i, 19349663*j), 83492791*k), &
                      n)

    end function hash

    function hash2(x, n)
        integer, intent(in) :: x
        integer, intent(in) :: n
        integer :: hash2

        hash2 = modulo(x, n)

    end function hash2

end module hashing
